package exer;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @author tongchen
 * @create 2023-01-17 17:31
 */
public class MyTimer {
    //创建锁对象
    private Object locker=new Object();
    //创建比较队列
    BlockingQueue<MyTask>queue=new PriorityBlockingQueue();
    //创建schedule方法,放入队列
    public void schedule(MyTask myTask) throws InterruptedException {

        queue.put(myTask);
        //解除睡眠
        synchronized (locker){
            locker.notifyAll();
        }
    }
    //创建构造器，实现队列元素的取出
    public MyTimer(){
        //创建线程
        Thread thread=new Thread(()->{
            //创建循环
            while(true) {
                //扩大synchronized范围，保证原子性
                synchronized (locker) {
                    //取出元素
                    try {
                        MyTask task = queue.take();
                        //判断是否到达该执行的时间
                        long time = System.currentTimeMillis();
                        if (time >= task.getTime()) {
                            //执行
                            task.getRunnable().run();
                        } else {
                            long gap = task.getTime() - time;
                            //睡眠并且重新放入,睡眠的目的在于避免cpu做无用的消耗

                                locker.wait(gap);

                            //重新放入
                            queue.put(task);
                        }


                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }
            }
        });
        thread.start();
        //创建新的线程，折中解决原子性
        Thread backGround=new Thread(()->{
            synchronized (locker){
                locker.notifyAll();
            }
            //休眠
            try {
                TimeUnit.SECONDS.sleep(1);
                //设置为后台线程
                Thread.currentThread().setDaemon(true);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        backGround.start();
    }
}
